package com.xxg.fileshand.base.ext

import android.content.res.Resources
import android.os.Handler
import android.view.View
import android.widget.Toast
import com.blankj.utilcode.util.AppUtils
import com.blankj.utilcode.util.ToastUtils
import com.xxg.fileshand.net.NetWorkException
import com.xxg.fileshand.R
import com.xxg.fileshand.app.App
import com.xxg.fileshand.constant.Constant
import com.xxg.fileshand.net.ApiService
import com.xxg.fileshand.net.BaseResponse
import com.xxg.fileshand.net.RetrofitManager
import com.xxg.fileshand.reader.ReaderUtils
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach

/**
 * date: 2020/09/07
 * desc: 拓展函数
 */
/**
 * 接口数据装换
 * @receiver BaseResponse<T>
 * @return T
 */
fun <T> BaseResponse<T>.dataConvert(

): T {
    when (code) {
        Constant.Code.OK -> {
            return data
        }

        Constant.Code.UnAuthorized -> {
            ReaderUtils.instance.release()
//            SpUtil.save("access_token", "")
            ToastUtils.showShort("登录过期，请重新登录")
            App.token = ""
            Handler().postDelayed({
                AppUtils.relaunchApp(true)
            }, 1000)
            throw NetWorkException(msg, code)
        }
        else -> {
            throw NetWorkException(msg, code)
        }
    }
}

/**
 * 接口数据无data 转换
 * @receiver BaseResponse<T>
 * @param loadState MutableLiveData<BaseActionEvent>?
 * @return Boolean
 */
fun <T> BaseResponse<T>.noDataConvert(): Boolean {
    when (code) {
        Constant.Code.OK -> {
            return true
        }

        Constant.Code.UnAuthorized -> {
//            SpUtil.save("access_token", "")
            throw NetWorkException(msg, code)
        }

        else -> {
            throw NetWorkException(msg, code)
        }

    }
}


fun <T> Flow<BaseResponse<T>>.subscribe(
    scope: CoroutineScope, success: (T) -> Unit,
    onServerError: (NetWorkException) -> Unit = {}
) {
    this.onEach {

        when (it.code) {
            Constant.Code.OK -> {
                success(it.data)
            }

            Constant.Code.UnAuthorized -> {
                throw NetWorkException(it.msg, it.code)
            }

            else -> {
                throw NetWorkException(it.msg, it.code)
            }
        }
    }.catch {
        val exception = NetWorkException(it)
        onServerError(exception)

    }.launchIn(scope)
}


/**
 * 单位转换
 * 正常编码中一般只会用到 [dp]/[sp] ;
 * 其中[dp]/[sp] 会根据系统分辨率将输入的dp/sp值转换为对应的px
 */
val Float.dp: Float
    get() = android.util.TypedValue.applyDimension(
        android.util.TypedValue.COMPLEX_UNIT_DIP,
        this,
        Resources.getSystem().displayMetrics
    )

val Int.dp: Int
    get() = android.util.TypedValue.applyDimension(
        android.util.TypedValue.COMPLEX_UNIT_DIP,
        this.toFloat(),
        Resources.getSystem().displayMetrics
    ).toInt()

val Float.sp: Float                 // [xxhdpi](360 -> 1080)
    get() = android.util.TypedValue.applyDimension(
        android.util.TypedValue.COMPLEX_UNIT_SP, this, Resources.getSystem().displayMetrics
    )

val Int.sp: Int
    get() = android.util.TypedValue.applyDimension(
        android.util.TypedValue.COMPLEX_UNIT_SP,
        this.toFloat(),
        Resources.getSystem().displayMetrics
    ).toInt()


/**
 * get set
 * 给view添加一个上次触发时间的属性（用来屏蔽连击操作）
 */
private var <T : View>T.triggerLastTime: Long
    get() = if (getTag(R.id.triggerLastTimeKey) != null) getTag(R.id.triggerLastTimeKey) as Long else 0
    set(value) {
        setTag(R.id.triggerLastTimeKey, value)
    }

/**
 * get set
 * 给view添加一个延迟的属性（用来屏蔽连击操作）
 */
private var <T : View>T.triggerDelay: Long
    get() = if (getTag(R.id.triggerDelayKey) != null) getTag(R.id.triggerDelayKey) as Long else -1
    set(value) {
        setTag(R.id.triggerDelayKey, value)
    }

/**
 * 判断时间是否满足再次点击的要求（控制点击）
 * @receiver T
 * @return Boolean
 */
private fun <T : View> T.clickEnable(): Boolean {
    var clickable = false
    val currentClickTiem = System.currentTimeMillis()
    if (currentClickTiem - triggerLastTime >= triggerDelay) {
        clickable = true
    }
    triggerLastTime = currentClickTiem
    return clickable
}

/***
 * 带延迟过滤点击事件的 View 扩展 防止快速点击
 * @param delay Long 延迟时间，默认500毫秒
 * @param block: (T) -> Unit 函数
 * @return Unit
 */

fun <T : View> T.clickWithTrigger(delay: Long = 500, block: (T) -> Unit) {
    triggerDelay = delay
    setOnClickListener {
        if (clickEnable()) {
            block(this)
        }
    }
}

/**
 * 日志打印拓展
 * @receiver Any
 * @param tag String
 */
fun Any.logd(tag: String = "logd----->") {
//    Timber.tag(tag).d(this.toString())
}

/**
 * 日志打印拓展
 * @receiver Any
 * @param tag String
 */
fun Any.loge(tag: String = "loge----->") {
//    Timber.tag(tag).e(this.toString())
}

/**
 * @desc 多个view执行同样的方法
 *  eg:  多个view点击时 跳转同一个页面
 */
fun clickWithMultiView(vararg v: View, block: () -> Unit) {
    v.forEach {
        it.clickWithTrigger {
            block.invoke()
        }
    }
}

fun getApiService(): ApiService {
    return RetrofitManager.build().create(ApiService::class.java)
}